#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>

namespace ns_protocol
{
// #define MYSELF 0

    // 定义空格字符及其长度（使用strlen而非sizeof，因为后者会返回整个字符串数组的大小）
    #define SPACE " "
    #define SPACE_LEN strlen(SPACE)

    // 定义消息分隔符及其长度（同样使用strlen）
    #define SEP "\r\n"
    #define SEP_LEN strlen(SEP)

    class Request
    {
    public:
        // 1. 自定义序列化方法，格式为 "length\r\nx_ op_ y_\r\n"
        // 2. 使用JsonCpp库进行序列化
        std::string Serialize()
        {
#ifdef MYSELF// 自定义序列化：拼接字符串并返回
            std::string str;
            str = std::to_string(x_);
            str += SPACE;
            str += op_;
            str += SPACE;
            str += std::to_string(y_);
            return str;
#else// 使用JsonCpp序列化：创建Json对象，填充数据，然后使用FastWriter写入字符串并返回
            Json::Value root;
            root["x"] = x_;
            root["y"] = y_;
            root["op"] = op_;
            Json::FastWriter writer;
            return writer.write(root);
#endif
        }
        // 反序列化字符串 "x_ op_ y_"，例如 "1234 + 5678"
        bool Deserialized(const std::string &str)
        {
#ifdef MYSELF// 自定义反序列化：解析字符串，提取x、y和op值
            std::size_t left = str.find(SPACE);
            if (left == std::string::npos)
                return false;
            std::size_t right = str.rfind(SPACE);
            if (right == std::string::npos)
                return false;
            x_ = atoi(str.substr(0, left).c_str());
            y_ = atoi(str.substr(right + SPACE_LEN).c_str());
            if (left + SPACE_LEN > str.size())
                return false;
            else
                op_ = str[left + SPACE_LEN];
            return true;
#else// 使用JsonCpp反序列化：创建Json对象，使用Reader解析字符串，然后从Json对象中提取数据
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);
            x_ = root["x"].asInt();
            y_ = root["y"].asInt();
            op_ = root["op"].asInt();
            return true;
#endif
        }

    public:
        Request() {} // 默认构造函数
        Request(int x, int y, char op) : x_(x), y_(y), op_(op) {} // 构造函数
        ~Request() {} // 析构函数

    public:
        //格式： x_ op y_ 或 y_ op x_
        int x_;   // 未知整数
        int y_;   // 未知整数
        char op_; // 运算符：'+' '-' '*' '/' '%'
    };

    // 定义响应类，用于封装响应相关的数据和序列化/反序列化方法
    class Response
    {
    public:
        // 序列化方法，生成 "code_ result_" 格式的字符串
        std::string Serialize()
        {
#ifdef MYSELF
            std::string s;
            s = std::to_string(code_);
            s += SPACE;
            s += std::to_string(result_);

            return s;
#else
            Json::Value root;
            root["code"] = code_;
            root["result"] = result_;
            root["xx"] = x_;
            root["yy"] = y_;
            root["zz"] = op_;
            Json::FastWriter writer;
            return writer.write(root);
#endif
        }
        // 反序列化字符串 "code_ result_"，例如 "111 100"
        bool Deserialized(const std::string &s)
        {
#ifdef MYSELF
            std::size_t pos = s.find(SPACE);
            if (pos == std::string::npos)
                return false;
            code_ = atoi(s.substr(0, pos).c_str());
            result_ = atoi(s.substr(pos + SPACE_LEN).c_str());
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(s, root);
            code_ = root["code"].asInt();
            result_ = root["result"].asInt();
            x_ =  root["xx"].asInt();
            y_ =  root["yy"].asInt();
            op_ =  root["zz"].asInt();
            return true;
#endif
        }

    public:
        Response() {} // 默认构造函数
        Response(int result, int code, int x, int y, char op) 
            : result_(result), code_(code), x_(x), y_(y), op_(op) {} // 构造函数
        ~Response() {} // 析构函数

    public:
        // result_：计算结果
        // code_：计算结果的状态码（例如：0, 1, 2, 3）
        int result_;
        int code_;

        int x_;
        int y_;
        char op_;
    };

    // 接收完整的报文
    bool Recv(int sock, std::string *out)
    {
        // 创建缓冲区接收数据
        char buffer[1024];

        // 使用recv接收数据
        ssize_t s = recv(sock, buffer, sizeof(buffer) - 1, 0); // 例如：接收到 "9\r\n123+789\r\n"

        if (s > 0)
        {
            buffer[s] = 0;
            *out += buffer; // 将接收到的数据添加到输出字符串中
        }
        else if (s == 0)
        {
            return false;
        }
        else
        {
            // std::cout << "recv error" << std::endl;
            return false;
        }
        return true;
    }

    void Send(int sock, const std::string str)
    {
        int n = send(sock, str.c_str(), str.size(), 0);
        if (n < 0)
            std::cout << "send error" << std::endl;
    }

    // 解码缓冲区中的报文，格式为 "length\r\nmessage\r\n..."
    // 示例：解码 "10\r\nabc"
    std::string Decode(std::string &buffer)
    {
        std::size_t pos = buffer.find(SEP);
        if(pos == std::string::npos) return ""; // 未找到分隔符，返回空字符串

        int size = atoi(buffer.substr(0, pos).c_str()); // 提取长度字段
        int surplus = buffer.size() - pos - 2*SEP_LEN; // 计算剩余缓冲区长度

        if(surplus >= size) // 如果剩余缓冲区长度大于等于报文长度
        {
            // 至少存在一个完整的报文，可以进行提取
            buffer.erase(0, pos + SEP_LEN); // 移除长度字段及分隔符
            std::string s = buffer.substr(0, size); // 提取报文
            buffer.erase(0, size + SEP_LEN); // 移除已处理的报文及分隔符
            return s; // 返回解码后的报文
        }
        else
        {
            return ""; // 剩余缓冲区不足以构成一个完整报文，返回空字符串
        }
    }

    // 对字符串进行编码，添加长度前缀和分隔符，格式为 "length\r\nmessage\r\n"
    // 示例：编码 "XXXXXX" 为 "123\r\nXXXXXX\r\n"
    std::string Encode(std::string &s)
    {
        std::string new_package = std::to_string(s.size());
        new_package += SEP;
        new_package += s;
        new_package += SEP;
        return new_package;
    }
}